/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.pheelicks.app.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.render.BlendMode;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.bundle.IBundleManager;
import ohos.media.audio.AudioRenderer;
import ohos.security.SystemPermission;

import com.pheelicks.app.ResourceTable;
import com.pheelicks.app.utils.PlaySoundUtil;
import com.pheelicks.app.utils.TunnelPlayerWorkaround;
import com.pheelicks.visualizer.VisualizerView;
import com.pheelicks.visualizer.renderer.BarGraphRenderer;
import com.pheelicks.visualizer.renderer.CircleBarRenderer;
import com.pheelicks.visualizer.renderer.CircleRenderer;
import com.pheelicks.visualizer.renderer.LineRenderer;

/**
 * 主界面
 *
 * @since 2021-05-12
 */
public class MainAbilitySlice extends AbilitySlice {
    private static final int MY_PERMISSIONS_REQUEST_MICROPHONE = 1000;
    private AudioRenderer mPlayer;
    private AudioRenderer mSilentPlayer;/* to avoid tunnel player issue */
    private VisualizerView mVisualizerView;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_main);
        findComponentById(ResourceTable.Id_bar).setClickedListener(this::barPressed);
        findComponentById(ResourceTable.Id_circle).setClickedListener(this::circlePressed);
        findComponentById(ResourceTable.Id_circle_bar).setClickedListener(this::circleBarPressed);
        findComponentById(ResourceTable.Id_line).setClickedListener(this::linePressed);
        findComponentById(ResourceTable.Id_clear).setClickedListener(this::clearPressed);
        findComponentById(ResourceTable.Id_start).setClickedListener(this::startPressed);
        findComponentById(ResourceTable.Id_stop).setClickedListener(this::stopPressed);
        mVisualizerView = (VisualizerView) findComponentById(ResourceTable.Id_visualizerView);

        // Start with just line renderer
        addLineRenderer();
    }

    @Override
    public void onActive() {
        super.onActive();
        if (verifySelfPermission(SystemPermission.MICROPHONE) != IBundleManager.PERMISSION_GRANTED) {
            // 应用未被授予权限
            if (canRequestPermission(SystemPermission.MICROPHONE)) {
                // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
                requestPermissionsFromUser(
                    new String[]{SystemPermission.MICROPHONE}, MY_PERMISSIONS_REQUEST_MICROPHONE);
            } else {
                // 显示应用需要权限的理由，提示用户进入设置授权
                terminate();
            }
        } else {
            // 权限已被授予
            getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> initPlayer());
        }
    }

    @Override
    protected void onBackground() {
        stopPressed(mVisualizerView);
        cleanUp();
        super.onBackground();
    }

    @Override
    protected void onStop() {
        cleanUp();
        super.onStop();
    }

    private void initPlayer() {
        PlaySoundUtil playSoundUtil = new PlaySoundUtil();
        playSoundUtil.loadSound("test.wav");
        mPlayer = playSoundUtil.getAudioRenderer();

        // We need to link the visualizer view to the media player so that
        // it displays something
        mVisualizerView.link(mPlayer, getContext());

        playSoundUtil.start();
    }

    private void cleanUp() {
        if (mPlayer != null) {
            mVisualizerView.release();
            mPlayer.release();
            mPlayer = null;
        }

        if (mSilentPlayer != null) {
            mSilentPlayer.release();
            mSilentPlayer = null;
        }
    }

    // Workaround (for Galaxy S4)
    //
    // "Visualization does not work on the new Galaxy devices"
    //    https://github.com/felixpalmer/visualizer/issues/5
    //
    // NOTE:
    //   This code is not required for visualizing default "test.wav" file,
    //   because tunnel player is used when duration is longer than 1 minute.
    //   (default "test.wav" file: 8 seconds)
    //
    private void initTunnelPlayerWorkaround() {
        // Read "tunnel.decode" system property to determine
        // the workaround is needed
        if (TunnelPlayerWorkaround.isTunnelDecodeEnabled(this)) {
            mSilentPlayer = TunnelPlayerWorkaround.createSilentMediaPlayer(this);
        }
    }

    // Methods for adding renderers to visualizer
    private void addBarGraphRenderers() {
        Paint paint = new Paint();
        paint.setStrokeWidth(50f);
        paint.setAntiAlias(true);
        paint.setColor(new Color(Color.argb(200, 56, 138, 252)));
        BarGraphRenderer barGraphRendererBottom = new BarGraphRenderer(16, paint, false);
        mVisualizerView.addRenderer(barGraphRendererBottom);

        Paint paint2 = new Paint();
        paint2.setStrokeWidth(12f);
        paint2.setAntiAlias(true);
        paint2.setColor(new Color(Color.argb(200, 181, 111, 233)));
        BarGraphRenderer barGraphRendererTop = new BarGraphRenderer(4, paint2, true);
        mVisualizerView.addRenderer(barGraphRendererTop);
    }

    private void addCircleBarRenderer() {
        Paint paint = new Paint();
        paint.setStrokeWidth(8f);
        paint.setAntiAlias(true);
        paint.setBlendMode(BlendMode.LIGHTEN);
        paint.setColor(new Color(Color.argb(255, 222, 92, 143)));
        CircleBarRenderer circleBarRenderer = new CircleBarRenderer(paint, 32, true);
        mVisualizerView.addRenderer(circleBarRenderer);
    }

    private void addCircleRenderer() {
        Paint paint = new Paint();
        paint.setStrokeWidth(3f);
        paint.setAntiAlias(true);
        paint.setColor(new Color(Color.argb(255, 222, 92, 143)));
        CircleRenderer circleRenderer = new CircleRenderer(paint, true);
        mVisualizerView.addRenderer(circleRenderer);
    }

    private void addLineRenderer() {
        Paint linePaint = new Paint();
        linePaint.setStrokeWidth(1f);
        linePaint.setAntiAlias(true);
        linePaint.setColor(new Color(Color.argb(88, 0, 128, 255)));

        Paint lineFlashPaint = new Paint();
        lineFlashPaint.setStrokeWidth(5f);
        lineFlashPaint.setAntiAlias(true);
        lineFlashPaint.setColor(new Color(Color.argb(188, 255, 255, 255)));
        LineRenderer lineRenderer = new LineRenderer(linePaint, lineFlashPaint, true);
        mVisualizerView.addRenderer(lineRenderer);
    }

    // Actions for buttons defined in xml
    public void startPressed(Component view) {
        if (mPlayer.getState() == AudioRenderer.State.STATE_PLAYING) {
            return;
        }
        getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> initPlayer());
    }

    public void stopPressed(Component view) {
        mPlayer.pause();
    }

    public void barPressed(Component view) {
        addBarGraphRenderers();
    }

    public void circlePressed(Component view) {
        addCircleRenderer();
    }

    public void circleBarPressed(Component view) {
        addCircleBarRenderer();
    }

    public void linePressed(Component view) {
        addLineRenderer();
    }

    public void clearPressed(Component view) {
        mVisualizerView.clearRenderers();
    }

    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_MICROPHONE: {
                // 匹配requestPermissions的requestCode
                if (grantResults.length > 0
                    && grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
                    // 权限被授予
                    // 注意：因时间差导致接口权限检查时有无权限，所以对那些因无权限而抛异常的接口进行异常捕获处理
                    getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> initPlayer());
                }
                return;
            }
            default:
                break;
        }
    }
}
